<template>
  <nut-form style="height: calc(100vh - 50px)" ref="formRef" :model-value="form.formData" :rules="rules">
    <nut-form-item v-for="item in formList" :key="item.prop" :prop="item.prop" :label="item.name">
      <template v-if="item.type === 'input'">
        <nut-input
            class="nut-input-text ml-4"
            v-model="form.formData[item.prop]"
            type="text"
            :placeholder="`请输入${item.name}`"
            @blur="onCustomBlurValidate(item.prop)"
        />
      </template>
      <template v-if="item.type === 'select'">
        <nut-cell
            is-link
            @click="form.selectShow[item.prop] = true"
        >
          {{form.formData[item.value] ? form.formData[item.value]: `请选择${item.name}`}}
        </nut-cell>
        <nut-popup position="bottom" v-model:visible="form.selectShow[item.prop]">
          <nut-picker
              :columns="item.option"
              v-model="form.formData[item.prop]"
              :title="`请选择${item.name}`"
              @confirm="({ selectedOptions, selectedValue })=> onConfirm({selectedOptions, selectedValue},item.prop)"
              @cancel="form.selectShow[item.prop] = false"
          >
          </nut-picker>
        </nut-popup>
      </template>
      <template v-else-if="item.type === 'inputNumber'">
        <nut-input-number
            v-model="form.formData[item.prop]"
            :min="0"
            :step="item.isDecimal ? 0.5 : 1"
            :decimal-places="item.isDecimal ? 1 : 0"
            button-size="30px"
            input-width="120px"
            @blur="onCustomBlurValidate(item.prop)"
            @change="onCustomBlurValidate(item.prop)"
        />
      </template>
      <template v-else-if="item.type === 'inputTime'">
        <nut-cell
            @click="form.selectShow[item.prop] = true"
        >
          {{form.formData[item.prop] ? form.formData[item.prop]: `请选择${item.name}`}}
        </nut-cell>
        <nut-popup  position="bottom" v-model:visible="form.selectShow[item.prop]">
          <nut-date-picker
              v-model="form.formData[item.value]"
              :is-show-chinese="true"
              :three-dimensional="false"
              @confirm="({ selectedOptions, selectedValue })=>
               onConfirm({ selectedOptions, selectedValue},item.prop, 'inputTime')"
              @cancel="form.selectShow[item.prop] = false"
              :title="`请选择${item.name}`"
          ></nut-date-picker>
        </nut-popup>
      </template>
      <template v-else-if="item.type === 'upload'">
        <nut-uploader
            url="api/common/upload"
            accept="*"
            v-model:file-list="form.formData[item.file]"
            multiple
            maximum="1"
            is-preview
            is-deletable
            @success="({responseText})=> onSuccess({responseText}, item.prop)"
        />
      </template>
    </nut-form-item>
  </nut-form>
  <nut-sticky :bottom="0" position="bottom" class="w-full">
    <nut-button
        shape="square"
        type="primary"
        :loading="isLoading"
        @click="onSubmit"
    >
      提交
    </nut-button>
    <nut-button shape="square" @click="onReset">重置</nut-button>
  </nut-sticky>
</template>

<script lang="ts">

import {defineComponent, PropType, reactive, ref, toRaw, watch} from "vue";
import {ItemsConfig, FormData} from "@/components/common/form";
import {FormRules} from "@nutui/nutui/dist/types/__VUE/form/types";


export default defineComponent ({
  props: {
    formList: {
      type: Object as PropType<ItemsConfig>,
      // eslint-disable-next-line vue/require-valid-default-prop
      default: () => [],
      require: true
    },
    formData: {
      type: Object as PropType<FormData>,
      default: () => {},
      require: true
    },
    selectShow: {
      type: Object as PropType<FormData>,
      default: () => {},
      require: false
    },
    rules: {
      type: Object as PropType<FormRules>,
      default: () => ({}),
    },
  },
  emits: ['submit','reset','update:formData',],
  setup: function (props, {emit, expose}) {

    const form = reactive<{
      formData: FormData
      formList: ItemsConfig
      selectShow: FormData
    }>({
      formData: toRaw(props.formData),
      formList: toRaw(props.formList),
      selectShow: toRaw(props.selectShow),
    })
    const formRef = ref()
    const isLoading = ref(false)

    expose({
      ref: formRef
    })

    watch<FormData>(()=> props.formData,(n,o) => {
      if (n !== o) {
        form.formData = n
      }
    })

    watch(
        () => form.formData,
        (n) => {
          emit('update:formData', n)
        },
        { deep: true }
    )

    watch(()=> props.selectShow, (n) => {
      form.selectShow = n
    })

    watch<ItemsConfig>(()=> props.formList,(n) => {
      form.formList = n
    },{deep: true})

    const onCustomBlurValidate = (prop: string) => {
      formRef.value.validate(prop)
    }

    const onConfirm = ({selectedOptions, selectedValue}, prop: string, type: string | undefined) => {
      if (type === 'inputTime') {
        form.formData[prop] = selectedValue.map((val) => val).join('-');
      } else {
        form.formData[`${prop}Text`]= selectedOptions.map((val) => val.text).join('');
        form.formData[prop] = selectedOptions.map((val) => val.value).join('');
      }
      form.selectShow[prop] = false
      onCustomBlurValidate(prop)
    }

    const onSubmit = async () => {
      if (!formRef.value) return
      try {
        formRef.value.validate().then(res => {
          if (res.valid) {
            emit('submit', form.formData)
            isLoading.value = true;
            setTimeout(() => {
              isLoading.value = false;
            }, 2000);
          }
        })
      } catch (error) {
        console.log('FormWithoutSetup submit =>', error)
      }
    }

    const onReset = () => {
      if (!formRef.value) return false
      formRef.value.reset()
      emit('reset')
    }
    const onSuccess = ({responseText}, prop: string) => {
      form.formData[prop] = JSON.parse(responseText).data
    }

    return {
      formRef,
      form,
      isLoading,
      onCustomBlurValidate,
      onSuccess,
      onReset,
      onSubmit,
      onConfirm,
    }
  }
})

</script>

<style scoped lang="scss">
:deep(.nut-input) {
  .input-text {
    @apply pl-4;
  }
}
:deep(.nut-form-item__body__tips) {
  @apply pl-4;
}
:deep(.nut-button) {
  width: 50%;
  height: 50px;
  position: relative;
  bottom: 0;
}
</style>